import datetime
import json
import math
import random
import sys
import time

from selenium.webdriver.common.by import By

from libs import config
from libs.account import Account
from libs.action import WebDriverAction
from libs.game import Game, _get_snapshot
from libs.image import ImageTool
from libs.log import Log
from libs.movement import Movement
from libs.price import get_floor_price, get_average_price
from libs.task_helper import TaskHelper
from libs.trade_helper import TradeHelper
from libs.window import AdsWindow


def craft(x, y, item_name, collect_after=None):
    for _ in range(2):
        try:
            action.click_by_offset(x, y)
            time.sleep(1)
            title = action.find_element(By.XPATH,
                                        f"//div[@class='Crafting_detailsTitle__bGjKU']//div[1]",
                                        'Title', 3)
            if title is None or title.text != item_name:
                back_button = action.find_element(By.XPATH, f"//button[text()='Back']", 'BackButton', 1)
                if back_button:
                    back_button.click()
                    time.sleep(1)
                opt = action.find_element(By.XPATH,
                                          f"//div[@class='Crafting_craftingRecipeItem__vnhBH']//span[text()='{item_name}']",
                                          item_name, 3)
                if opt is None:
                    action.escape()
                    time.sleep(1)
                    action.click()
                    opt = action.find_element(By.XPATH,
                                              f"//div[@class='Crafting_craftingRecipeItem__vnhBH']//span[text()='{item_name}']",
                                              item_name, 3)
                opt.click()
                break
        except:
            action.escape()
            action.escape()
            time.sleep(3)
    time.sleep(1)
    craft_count = 0
    for _ in range(10):
        craft_button = action.find_element(By.CLASS_NAME, "Crafting_craftingButton__Qd6Ke", 'CraftButton', 2)
        if craft_button is None:
            action.escape()
            action.click_by_offset(x, y)
            time.sleep(1)
            log.debug('no craft button')
            continue
        if craft_button.text == 'Collect':
            if craft_button.is_enabled():
                craft_button.click()
                time.sleep(3)
                continue
        if craft_button.text == 'Create':
            if craft_button.is_enabled():
                craft_button.click()
                time.sleep(random.randint(1, 2))
                craft_count = 1
            break
        time.sleep(1)
    if craft_count > 0 and collect_after is not None:
        time.sleep(collect_after)
        for _ in range(5):
            craft_button = action.find_element(By.CLASS_NAME, "Crafting_craftingButton__Qd6Ke", 'CraftButton', 2)
            if craft_button.text == 'Collect':
                if craft_button.is_enabled():
                    craft_button.click()
                    time.sleep(1)
                    break
            time.sleep(1)
    return craft_count


wood_items = {
    "Log Decoration": {
        "sell_name": "Log Decoration",
        "items": {
            "Whittlewood Log": 24,
            "Stick": 6,
            "Crafting Mix": 1,
        },
        "energy_cost": 1,
        "wait_seconds": 60,
    },
    "Empty Barrel": {
        "sell_name": "Empty Barrel",
        "items": {
            "Whittlewood Plank": 12,
            "Crafting Mix": 1,
        },
        "energy_cost": 1,
        "wait_seconds": 60,
    },
    "Purple Liquid Barrel": {
        "sell_name": "Barrel of Purple",
        "items": {
            "Whittlewood Plank": 12,
            "Blue Grumpkin": 12,
            "Crafting Mix": 1,
        },
        "energy_cost": 2,
        "wait_seconds": 90,
    },
    "Wooden Stool": {
        "sell_name": "Wooden Stool",
        "items": {
            "Stick": 8,
        },
        "energy_cost": 1,
        "wait_seconds": 30,
    }
}


def decide_to_make():
    # 检查木工技能等级
    if wood_skill < 3:
        return None, None


    account = Account().get(user_id)
    fee_rate = float(account.get('fee_rate', 20))
    log.debug(f'fee_rate={fee_rate}')
    # 计算收益
    chosen_key = None
    chosen_cost = None
    chosen_profit = 0
    for item_key in wood_items:
        config = wood_items.get(item_key)
        wait_seconds = config.get('wait_seconds')
        item_cost, item_sell_price = get_profit(item_key)
        item_profit = item_sell_price * (100 - fee_rate)/100 - item_cost
        profit_per_minute = item_profit * 60 / wait_seconds
        log.debug(f'[{item_key}] cost={item_cost}, sell_price={item_sell_price}, profit={profit_per_minute}, min_profit_limit={min_profit_limit}')
        if profit_per_minute > min_profit_limit and profit_per_minute > chosen_profit:
            chosen_key = item_key
            chosen_profit = profit_per_minute
            chosen_cost = item_cost

    return chosen_key, chosen_cost


def get_profit(item_key):
    config = wood_items.get(item_key)
    items = config.get('items')
    item_cost = 0
    for item_name in items:
        qty = items.get(item_name)
        price = get_average_price(item_name)
        item_cost += price * qty

    sell_name = config.get('sell_name')
    item_sell_price = get_floor_price(sell_name, 10)

    return item_cost, item_sell_price


if __name__ == "__main__":
    parser = TaskHelper.default_args_parser('Wine')
    args = parser.parse_args()
    task_helper = TaskHelper.from_args(args)

    user_id = args.user_id
    log = Log(user_id)

    min_profit_limit = config.get_account(user_id).get('wood', 300)
    snapshot = _get_snapshot(user_id)
    wood_skill = snapshot.get('skills', {}).get('wood', 0)
    coin = snapshot.get('coin', 0)
    log.debug(f'wood={wood_skill}, coin={coin}')

    make_item, cost = decide_to_make()
    if make_item is not None:
        time.sleep(60)
        make_item, cost = decide_to_make()

    if make_item is None:
        log.info('nothing to make')
        task_helper.task_giveup()
        task_helper.wood(delay_seconds=60 * 30)  # 三十分钟后重试
        sys.exit()
    # make_item = 'Wooden Stool'
    log.info(f'decide to make {make_item}')

    driver = AdsWindow(user_id).open(False)

    game = Game(driver, user_id)
    action = WebDriverAction(driver)
    movement = Movement(driver)
    image_tool = ImageTool(driver)
    trade_helper = TradeHelper(driver, user_id)

    run_minutes = 20
    # run_minutes = 0
    item_config = wood_items.get(make_item)
    wait_seconds = item_config.get('wait_seconds', 60)
    max_count = math.floor(run_minutes * (60 / wait_seconds))
    log.info(f'make_count={max_count}')
    if coin < cost * max_count + 10000:
        log.info('coin_not_enough')
        task_helper.task_giveup()
        task_helper.wood(delay_seconds=60 * 30)  # 三十分钟后重试
        sys.exit()

    try:
        game.enter_game()
        game.collect_mail()
        snapshot = game.snapshot(user_id, 'before wood')

        # 买材料, 检查背包格子数量
        game.get_backpack()
        buy_items = {}
        need_items = item_config.get('items', [])
        space_needed = 1
        for item_name in need_items:
            need_qty = need_items.get(item_name)
            has_qty = game.get_backpack_qty(item_name)
            buy_qty = max(0, need_qty * max_count - has_qty)
            space_needed += math.ceil(buy_qty / 99)
            buy_items[item_name] = buy_qty

        # 卖
        trade_helper.goto_sell_position()
        trade_helper.open_shop_sell()
        for key in wood_items:
            if key == make_item:
                continue
            row = wood_items.get(key)
            sell_name = row.get('sell_name')
            sell_qty = game.get_backpack_qty(sell_name)
            trade_helper.sell_item(sell_name, 1111, price_delta=-1)
            time.sleep(1)
            for item_sell_name in row.get('items'):
                if item_sell_name not in buy_items:
                    item_sell_qty = game.get_backpack_qty(item_sell_name)
                    if item_sell_qty > 0:
                        trade_helper.sell_item(item_sell_name, 1111, price_delta=-1)
                        time.sleep(1)

        space = game.get_backpack_space()
        log.info(f'wood_prepare: space={space}, buy={json.dumps(buy_items)}')
        if space > space_needed:
            trade_helper.goto_buy_position()
            filter_input = trade_helper.open_market_buy()
            for buy_item_name in buy_items:
                buy_item_qty = buy_items.get(buy_item_name)
                trade_helper.market_buy_item(filter_input, buy_item_name, buy_item_qty)
            action.escape()
            time.sleep(0.5)
            action.escape()
            time.sleep(1)

        # 做木工
        moi_loc = None
        for _ in range(3):
            moi_loc = image_tool.find_target('moi.png')
            if moi_loc is None:
                action.goto_moi()
                continue
            break
        moi_x, moi_y = moi_loc
        make_count = 0
        for _ in range(max_count * 2):
            result = craft(moi_x, moi_y, make_item, collect_after=wait_seconds)
            if result > 0:
                make_count += 1
                log.debug(f'make {make_item}[{make_count}/{max_count}]')
            else:
                break

        action.escape()
        action.escape()

        game.get_backpack()
        trade_helper.goto_sell_position()
        trade_helper.open_shop_sell()
        sell_name = item_config.get('sell_name')
        trade_helper.sell_item(sell_name, 1111, price_delta=-1, min_price=cost)
        # trade_helper.sell_item(sell_name, 1111, price_delta=-1)

        action.escape()
        action.escape()

        for _ in range(3):
            time.sleep(10)
            game.collect_mail()
            action.escape()
            action.escape()

        game.get_backpack()
        game.snapshot(user_id, 'after wood')
        task_helper.task_success()
        hour = datetime.datetime.now().hour
        if hour == int(user_id) % 24:
            task_helper.wood(delay_seconds=random.randint(60 * 60 * 6, 60 * 60 * 8))  # 休息六到八小时
        else:
            task_helper.wood(delay_seconds=random.randint(60 * 10, 60 * 60))  # 重试

    except Exception as e:
        task_helper.task_fail()
        task_helper.wood(retry=True)
        raise e
